﻿#include "TopLogin.h"
#include <QPushButton>
#include <QMouseEvent>
#include <QPoint>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QLabel>
#include <QFile>
#include <QString>
#include <QDebug>
#include <QDir>
#include <QCheckBox>
#include <QTimer>
#include <QTime>
#include <QApplication>
#include <QPropertyAnimation>

#include "titleBar.h"
#include "LoginSettingDlg.h"
#include "LoginRegDlg.h"
#include "MyApp.h"
#include "unit.h"
#include "ClientSocket.h"
#include "Msg.h"
#include "CustomWidget.h"
#include "MainWindow.h"
#include "LoginAccountListWidget.h"
#include "global.h"
#include "DataBaseMagr.h"


//下面这个样式表可以放到一个单独qss文件
#define NAMEBTN_STYLE "QPushButton{                                 \
                        border:none;                                \
                        background-color: rgba(255, 225, 255, 0);   \
                        font: bold 16px;                            \
                        color:rgba(0, 0, 0, 70);}"                  \
                      "QPushButton:hover{                           \
                        border:none;                                \
                        background-color: rgba(255, 225, 255, 0);   \
                        font: bold 16px;                            \
                        color:rgba(0, 0, 0, 90);}"

TopLogin::TopLogin(QWidget *parent) : BaseWindow(parent),
    m_bConnected(false),
    m_bLogin(false),
    m_pClientSocket(new ClientSocket()),
    m_thread()
{
    this->setObjectName("TopLogin");
    this->setAttribute(Qt::WA_DeleteOnClose);
    initUi();
    initConnect();
    initNetWork();
    loadAccountFile();
}

TopLogin::~TopLogin()
{
    qDebug() << "TopLogin::~TopLogin()";
    m_pAccountListWidget->clear();
    int count=m_pAccountListWidget->count();
    for(int i=0;i<count;i++)
    {
       QListWidgetItem *item = m_pAccountListWidget->takeItem(0);
       delete item;
    }

    m_thread.quit();
    m_thread.wait();
    qApp->quit();
}

void TopLogin::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton){
         m_windowPos = this->pos();
         m_mousePos = event->globalPos();
         m_bMousePress = true;

         m_pAccountListWidget->hide();
    }
}

void TopLogin::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        m_bMousePress = false;
}

void TopLogin::mouseMoveEvent(QMouseEvent *event)
{
    if ((event->buttons() & Qt::LeftButton) && m_bMousePress == true){
        move(m_windowPos + (event->globalPos() - m_mousePos));
    }
}

bool TopLogin::eventFilter(QObject *obj, QEvent *evt)
{
    if(obj == m_pNameEdit)//lineedit的
    {/*
        if(evt->type()==QEvent::FocusOut)
        {
            m_pAccountListWidget->hide();
        }*/
        if(evt->type() == QEvent::FocusIn)
        {
            m_pAccountListWidget->hide();
        }
        return false;
    }
    else if(obj == m_pAccountListWidget)
    {
        if(evt->type()==QEvent::FocusOut)
        {
            m_pAccountListWidget->hide();
        }
        return false;
    }
    else
    {
        return QWidget::eventFilter(obj,evt);
    }

}

void TopLogin::initUi(void)
{
    Widget* pMainWin =  &m_MainWin;

    this->setMouseTracking(true);
    m_pLoginSettingDlg.reset(new LoginSettingDlg());
    m_pLoginRegDlg.reset(new LoginRegDlg());
    //m_pLoginSettingDlg->setAttribute(Qt::WA_ShowModal,true);    //设置为模态显示
    //m_pLoginRegDlg->setAttribute(Qt::WA_ShowModal,true);
    m_pLoginRegDlg->setWindowModality(Qt::ApplicationModal);    //设置为模态显示
    //窗体属性
    setWindowFlags(Qt::FramelessWindowHint);
    m_pTitle = new titleBar(pMainWin);
    m_pTitle->setWinTitle(tr("逐梦通讯1.0 正在连接服务器..."));
    m_pTitle->move(0,0);
    m_pTitle->resize(550,24);
    //setWindowTitle(tr("逐梦通讯"));
    setWindowIcon(QIcon(":/Images/resource/flamingo.ico"));
    pMainWin->setFixedSize(550,350);
    setMinimumSize(0, 0);
    //设置背景图片
    pMainWin->m_bIsShowBG = false;
    pMainWin->setAutoFillBackground(true); // 这句要加上, 否则可能显示不出背景图.
    QPalette palette = pMainWin->palette();
    palette.setBrush(QPalette::Window,
                QBrush(QPixmap(":/Images/resource/LoginDlgBg.png").scaled(// 缩放背景图.
                pMainWin->size(),
                Qt::IgnoreAspectRatio,
                Qt::SmoothTransformation)));             // 使用平滑的缩放方式
    pMainWin->setPalette(palette);

    m_pInsertWidget = new QWidget(pMainWin);
    m_pInsertWidget->setFixedSize(550,200);
    m_pInsertWidget->move(0,160);
    //标签--账号、密码
    //QString nameBtn_style = NAMEBTN_STYLE;
    QLabel *pUserName = new QLabel("账号:",m_pInsertWidget);
    //pUserName->move(130,165);
    pUserName->move(130,0);
    pUserName->setFixedHeight(30);
    m_pNameEdit = new QLineEdit(m_pInsertWidget);
    m_pNameEdit->setGeometry(185,0,180,30);
    m_pNameEdit->setPlaceholderText("请输入手机号");
    QRegExp regxSrv("\\d+");
    QValidator *validatorSrv = new QRegExpValidator(regxSrv, m_pNameEdit);
    m_pNameEdit->setValidator( validatorSrv );

    m_pAccountListBtn = new QPushButton(m_pInsertWidget);
    m_pAccountListBtn->setFixedSize(28,28);
    m_pAccountListBtn->setIcon(QPixmap(":/Images/resource/images/indicator_down.png"));
    m_pAccountListBtn->setObjectName("AccountListBtn");
    m_pAccountListBtn->setCursor(Qt::ArrowCursor);
    m_pAccountListWidget = new LoginAccountListWidget(m_pInsertWidget);
    m_pAccountListWidget->setGeometry(
                m_pNameEdit->x(),m_pNameEdit->height()+m_pNameEdit->y()+2,m_pNameEdit->width(),150);
    m_pAccountListWidget->raise();
    m_pAccountListWidget->hide();

    QHBoxLayout *layout = new QHBoxLayout;
    layout->setContentsMargins(0,0,1,0);
    layout->addStretch();
    layout->addWidget(m_pAccountListBtn);
    m_pNameEdit->setLayout(layout);

    m_pRegIdBtn = new QPushButton("注册账号",m_pInsertWidget);
    m_pRegIdBtn->setObjectName("AccountBtn");
    m_pRegIdBtn->move(385,0);
    m_pRegIdBtn->setFixedHeight(30);
    //m_pRegIdBtn->setStyleSheet(nameBtn_style);

    QLabel *pPasswdLabel = new QLabel("密码:",m_pInsertWidget);
    pPasswdLabel->move(130,50);
    pPasswdLabel->setFixedHeight(30);
    m_pPasswdEdit = new QLineEdit(m_pInsertWidget);
    m_pPasswdEdit->setGeometry(185,50,180,30);
    m_pPasswdEdit->setPlaceholderText("请输入密码");
    m_pPasswdEdit->setEchoMode(QLineEdit::Password);      //密码用小黑点
    m_pFindPasswdBtn = new QPushButton("找回密码",m_pInsertWidget);
    m_pFindPasswdBtn->setObjectName("AccountBtn");
    //m_pFindPasswdBtn->setStyleSheet(nameBtn_style);
    m_pFindPasswdBtn->move(385,50);
    m_pFindPasswdBtn->setFixedHeight(30);

    m_pboxRemberPwd = new QCheckBox("记住密码",m_pInsertWidget);
    m_pboxRemberPwd->move(155,100);
    m_pboxAutoLogin = new QCheckBox("自动登录",m_pInsertWidget);
    m_pboxAutoLogin->move(300,100);
    //登录框
    m_pLoginBtn = new QToolButton(pMainWin);
    m_pLoginBtn->setText(tr("登陆"));
    m_pLoginBtn->setGeometry(185,300,180,30);
    m_pLoginBtn->setObjectName("LoginBtn");
    //显示头像
    m_pPicHead = new QLabel(pMainWin);
    QPixmap picHead(":/Images/resource/DefBuddyHeadPic_bak.png");
    m_pPicHead->setPixmap(picHead);
    m_pPicHead->move(50,200);
    //登录中label
    m_plabelLogin = new QLabel(pMainWin);
    m_plabelLogin->move(245,210);
    m_plabelLogin->setText("登陆中...");
    m_plabelLogin->setVisible(false);

    m_pNameEdit->installEventFilter(this);
    m_pAccountListWidget->installEventFilter(this);
}

void TopLogin::initConnect(void)
{
    connect(m_pTitle->getCloseBtn(), &QPushButton::clicked, this, &TopLogin::close);
    connect(m_pTitle->getMinimizeBtn(), &QPushButton::clicked, [this]{ showMinimized(); });
    connect(m_pTitle->getMenuBtn(),&QPushButton::clicked,[this]{ m_pLoginSettingDlg->show(); });
    connect(m_pRegIdBtn,&QPushButton::clicked,this,&TopLogin::SltShowRegdlg);
    connect(m_pLoginSettingDlg.get(),&LoginSettingDlg::signalConfEdit,m_pClientSocket,&ClientSocket::ConnectToHost);
    connect(m_pAccountListWidget,&LoginAccountListWidget::itemClicked,this,&TopLogin::SltLoginAccountInfo);

    connect(m_pLoginBtn,&QToolButton::clicked,this,&TopLogin::SltClickedLoginBtn);
    connect(m_pLoginRegDlg->m_pOkBtn,&QPushButton::clicked,this,&TopLogin::SltRegister);
    connect(m_pAccountListBtn,&QPushButton::clicked,this,&TopLogin::SltShowAccountListWidget);
    connect(m_pNameEdit,&QLineEdit::textChanged,this,&TopLogin::SltNameEditTextChanged);
}

void TopLogin::initNetWork(void)
{
    m_pClientSocket->moveToThread(&m_thread);       //连同子类也移到到这个线程
    m_thread.start();

    //qRegisterMetaType<QJsonObject>("QJsonObject");
    //qRegisterMetaType<QJsonDocument>("QJsonDocument");

    connect(&m_thread,&QThread::finished,m_pClientSocket,&ClientSocket::deleteLater);
    connect(m_pClientSocket,&ClientSocket::signalStatus,this,&TopLogin::SltTcpStatus);
    connect(m_pClientSocket,&ClientSocket::sigUserInfo,this,&TopLogin::SltUserInfo);
    connect(this,&TopLogin::sigSend,m_pClientSocket,&ClientSocket::SltSend);
    connect(this,&TopLogin::sigConnectToHost,m_pClientSocket,&ClientSocket::ConnectToHost);
    Q_EMIT sigConnectToHost();
    //m_pClientSocket->ConnectToHost();
}

void TopLogin::loadAccountFile()
{
    //载入登录信息文件
    m_accountList.LoadFile(MyApp::m_strUsersFile);
    for(int i=0; i<m_accountList.GetCount(); i++)
    {
        LOGIN_ACCOUNT_INFO* accountInfo = m_accountList.m_arrLoginAccount[i];
        m_pAccountListWidget->addItem(new QListWidgetItem(QString(accountInfo->szUser)));
    }
    m_prerow = m_accountList.GetLastLoginUser();
    LOGIN_ACCOUNT_INFO *lastUser = m_accountList.GetAccountInfo(m_prerow);
    if(lastUser != NULL)
    {
        m_pNameEdit->setText(QString(lastUser->szUser));
        SltNameEditTextChanged(QString(lastUser->szUser));
        if(lastUser->bRememberPwd)
        {
            m_pboxRemberPwd->setChecked(true);
            m_pPasswdEdit->setText(QString(lastUser->szPwd));
        }
        if(lastUser->bAutoLogin)
        {
            m_pboxAutoLogin->setChecked(true);
            QTimer::singleShot(1000,this,&TopLogin::SltClickedLoginBtn);
        }
    }
}

void TopLogin::loadUserCfg()
{
    MyApp::m_bPlaySound = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","PlaySound",MyApp::m_bPlaySound).toBool();
    MyApp::m_bShowExitDlg = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","ShowExitDlg",MyApp::m_bPlaySound).toBool();
    MyApp::m_bMainWindowHide = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"UserConf","MainWindowHide",MyApp::m_bPlaySound).toBool();
}

void TopLogin::SltShowRegdlg()
{
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("未连接服务器，请等待！"));
        Q_EMIT sigConnectToHost();
        return;
    }
    m_pLoginRegDlg->show();
}

void TopLogin::SltUserInfo(const QJsonObject &userInfo)
{
    qDebug() <<"SltUserInfo";
    m_userInfo = userInfo;
}

void TopLogin::SltShowAccountListWidget()
{
    m_pAccountListWidget->raise();
    m_pAccountListWidget->show();
    m_pAccountListWidget->setFocus();
}

void TopLogin::SltLoginAccountInfo(QListWidgetItem *item)
{
    m_pNameEdit->setText(item->text());
    m_pAccountListWidget->hide();
}

void TopLogin::SltNameEditTextChanged(const QString &text)
{

    QString UserCfgFile = MyApp::m_strUsersPath + text + "/" + text + ".cfg";
    QFile file(UserCfgFile);
    if(file.exists())
    {
        QSettings settings(UserCfgFile, QSettings::IniFormat);
        settings.beginGroup("UserInfo");
        int FaceID = settings.value("FaceID",0).toInt();
        QPixmap picHead(QString(":/Images/resource/head/%1.png").arg(FaceID));
        m_pPicHead->setPixmap(picHead);
    }
    else
    {
        QPixmap picHead(QString(":/Images/resource/head/0.png"));
        m_pPicHead->setPixmap(picHead);
    }

    LOGIN_ACCOUNT_INFO *User = m_accountList.Find(text.data());
    if(User != NULL)
    {
        if(User->bRememberPwd)
        {
            m_pboxRemberPwd->setChecked(true);
            m_pPasswdEdit->setText(QString(User->szPwd));
            //记住密码的情况下，才勾选自动登录框
            if(User->bAutoLogin)
            {
                m_pboxAutoLogin->setChecked(true);
            }else
            {
                m_pboxAutoLogin->setChecked(false);
            }
        }
    }else
    {
        m_pboxRemberPwd->setChecked(false);
        m_pPasswdEdit->setText("");
        m_pboxAutoLogin->setChecked(false);
    }
}

/**
 * @brief LoginWidget::SltTcpStatus
 * 读取服务器返回的登陆信息状态
 * @param state
 */
void TopLogin::SltTcpStatus(const quint8 &status)
{
    switch(status)
    {
    case ConnectedHost:{
        m_bConnected = true;
        m_pTitle->setWinTitle(tr("逐梦通讯1.0 服务器已连接"));
    }
        break;
    case DisConnectedHost:{
        m_bConnected = false;
        m_pTitle->setWinTitle(tr("逐梦通讯1.0 服务器已断开"));
    }
        break;
    // 登陆验证成功
    case LoginSuccess:
    {
        qDebug() << "LoginSuccess";
        disconnect(m_pClientSocket,&ClientSocket::signalStatus,this,&TopLogin::SltTcpStatus);
        disconnect(m_pClientSocket,&ClientSocket::sigUserInfo,this,&TopLogin::SltUserInfo);
        //这部分代码整合到Myapp::initApp中去
        MyApp::m_strUserName = m_pNameEdit->text();
        MyApp::m_strUserPwd = m_pPasswdEdit->text();
        MyApp::m_strUserCfgFile = MyApp::m_strUsersPath + MyApp::m_strUserName + "/" + MyApp::m_strUserName + ".cfg";
        MyApp::s_strDatabasePath = MyApp::m_strUsersPath + MyApp::m_strUserName + "/ChatLog/";
        QDir dir(MyApp::s_strDatabasePath);
        if(!dir.exists())
        {
            dir.mkdir(MyApp::s_strDatabasePath);       //FIXME:check ret?
        }

        //加载用户设置
        loadUserCfg();
        //加载数据库
        DataBaseMagr::Instance()->OpenMessageDb(MyApp::s_strDatabasePath+"msg.db");
        //保存当前登录用户信息
        m_accountList.Modify(
                    m_pNameEdit->text().data(),
                    m_pPasswdEdit->text().data(),
                    0,
                    m_pboxRemberPwd->isChecked(),
                    m_pboxRemberPwd->isChecked() && m_pboxAutoLogin->isChecked());
        m_accountList.SetLastLoginUser(MyApp::m_strUserName.data());
        m_accountList.SaveFile(MyApp::m_strUsersFile);
        //延迟一秒展开主界面，方便用户取消登录
        myHelper::Sleep(1000);

        if(m_bLogin)
        {
            MainWindow *pMain=MainWindow::InitInstance();
            connect(pMain,&MainWindow::destroyed,this,&TopLogin::close);
            QPoint point= myHelper::FormInCenter(pMain);
            QSize size(400,700);
            point = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"MainDlg","position",point).toPoint();
            size = MyApp::GetSettingKeyValue(MyApp::m_strUserCfgFile,"MainDlg","size",size).toSize();
            pMain->move(point);
            pMain->resize(size);

            pMain->setAttribute(Qt::WA_DeleteOnClose);
            //pMain->show();
            this->hide();
            pMain->showNormal();
            pMain->activateWindow();
            pMain->setAttribute(Qt::WA_QuitOnClose,true);//这个属性一定需要在show后面设置，不然登录窗口关闭以后主界面直接退出
            //显示完主窗口以后再设置socket，获取个人信息，拉去好友列表
            //原因：topwidget中的签名需要在resizeevent执行以后，签名区域的widget宽度改变以后再设置签名信息
            //pMain->setSocket(m_pClientSocket,m_userInfo);
            Q_EMIT sigSend(msg_type_getofriendlist,QJsonObject());

        }
    }
        break;
    case LoginPasswdError:
    {
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        CMessageBox::Infomation("登录失败，请检查用户名和密码！");
    }
        break;
    case LoginNotRegister:
    {
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        CMessageBox::Infomation("账号未注册！");
    }
        break;
    case LoginRepeat:
    {
        m_pInsertWidget->setVisible(true);
        m_pPicHead->move(50,200);
        CMessageBox::Infomation("登录失败，该账户已登录！");
    }
        break;
    case RegisterOk:
    {
        CMessageBox::Infomation("该账号注册成功！请点击登录！");
        m_pNameEdit->setText(m_strRegPhoneNum);
        m_pPasswdEdit->setText(m_strRegPassword);
    }
        break;
    case RegisterFailed:
    {
        CMessageBox::Infomation("注册失败！请重新注册！");
    }
        break;
    case RegisterAlready:
    {
        CMessageBox::Infomation("该账号已注册！");
    }
    default:
        break;
    }
}

/**
 * @brief TopLogin::SltLogin    登录
 */
void TopLogin::SltLogin()
{
    //检查服务器是否连接
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("未连接服务器，请等待！"));
        m_pLoginBtn->setText(tr("登录"));
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        Q_EMIT sigConnectToHost();
        return;
    }
    //用户密码不为空
    if(m_pNameEdit->text().isEmpty())
    {
        CMessageBox::Infomation(tr("用户名不能为空！"));
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        return;
    }else if(m_pPasswdEdit->text().isEmpty())
    {
        CMessageBox::Infomation(tr("密码不能为空！"));
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        return;
    }
    //登录

    //Send msg...
    // 构建 Json 对象
    QJsonObject json;
    json.insert("username", m_pNameEdit->text());
    json.insert("password", m_pPasswdEdit->text());
    json.insert("clienttype", CLIENT_TYPE_PC);
    json.insert("status",STATUS_ONLINE);
    //QJsonDocument jsonData(json);
    Q_EMIT sigSend(msg_type_login,json);
}

void TopLogin::SltClickedLoginBtn()
{
    //登录动画
    if(!m_bLogin)
    {
        m_bLogin = true;
        m_pLoginBtn->setText(tr("取消登录"));

        m_pInsertWidget->setVisible(false);
        m_plabelLogin->setVisible(true);
        //这个animation会造成内存泄漏？或者程序关闭内存才释放？
        QPropertyAnimation *animation = new QPropertyAnimation(m_pPicHead, "pos");
        animation->setDuration(200);
        animation->setStartValue(QPoint(50, 200));
        animation->setEndValue(QPoint((this->width() - m_pPicHead->width()) / 2, 100));
        connect(animation, SIGNAL(finished()), this, SLOT(SltLogin()));

        animation->start(QAbstractAnimation::DeleteWhenStopped);
    }
    else
    {
        //取消登录以后需要重新连接信号到槽
        connect(m_pClientSocket,&ClientSocket::signalStatus,this,&TopLogin::SltTcpStatus);
        connect(m_pClientSocket,&ClientSocket::sigUserInfo,this,&TopLogin::SltUserInfo);

        m_bLogin = false;
        m_pInsertWidget->setVisible(true);
        m_plabelLogin->setVisible(false);
        m_pPicHead->move(50,200);
        m_pLoginBtn->setText(tr("登录"));
        Q_EMIT sigConnectToHost();
    }
}

/**
 * @brief SltRegister   注册
 */
void TopLogin::SltRegister()
{
    if(!m_bConnected)
    {
        CMessageBox::Infomation(tr("未连接服务器，请等待！"));
        Q_EMIT sigConnectToHost();
        return;
    }

    if(m_pLoginRegDlg->m_pEditRegPwd1->text() != m_pLoginRegDlg->m_pEditRegPwd2->text())
    {
        CMessageBox::Warning("密码不一致");
        return;
    }
	
    m_strRegPhoneNum = m_pLoginRegDlg->m_pEditPhone->text();
    m_strRegNickName = m_pLoginRegDlg->m_pEditNickName->text();
    m_strRegPassword = m_pLoginRegDlg->m_pEditRegPwd1->text();

    //Send msg...
    // 构建 Json 对象
    //{"username": "15380926632", "nickname": "沙僧", "password": "123456"}
    QJsonObject json;
    json.insert("username", m_strRegPhoneNum);
    json.insert("nickname", m_strRegNickName);
    json.insert("password", m_strRegPassword);
    //QJsonDocument jsonData(json);
    Q_EMIT sigSend(msg_type_register,json);
    m_pLoginRegDlg->close();
}
